﻿using AutoMapper;
using YDT_OrderService.Applications.DTOs;
using YDT_OrderService.Applications.Interfaces;
using YDT_OrderService.Domains.Entities;
using YDT_OrderService.Domains.Interfaces;

namespace YDT_OrderService.Applications.Services
{
    public class OrderService : IOrderService
    {
        private readonly IOrderRepository _orderRepository;
        private readonly IMapper _mapper;

        public OrderService(IOrderRepository orderRepository, IMapper mapper)
        {
            _orderRepository = orderRepository;
            _mapper = mapper;
        }

        public async Task<OrderDto> CreateOrderAsync(CreateOrderDto createOrderDto)
        {
            var orderSn = GenerateOrderSn();
            var order = new Order(
                createOrderDto.UserId,
                createOrderDto.OrderType,
                orderSn,
                createOrderDto.OrderName,
                createOrderDto.OrderTel,
                createOrderDto.OrderAddress,
                createOrderDto.OrderRemark
            );

            foreach (var itemDto in createOrderDto.OrderItems)
            {
                order.AddOrderItem(
                    itemDto.ProductId,
                    itemDto.ProductName,
                    itemDto.ProductUrl,
                    itemDto.ItemPrice,
                    itemDto.ItemCount
                );
            }

            await _orderRepository.AddAsync(order);
            return _mapper.Map<OrderDto>(order);
        }

        public async Task<bool> DeleteOrderAsync(Guid id)
        {
            var order = await _orderRepository.GetByIdAsync(id);
            if (order == null) return false;

            await _orderRepository.DeleteAsync(id);
            return true;
        }

        public async Task<IEnumerable<OrderDto>> GetAllOrdersAsync()
        {
            var orders = await _orderRepository.GetAllAsync();
            return _mapper.Map<IEnumerable<OrderDto>>(orders);
        }

        public async Task<OrderDto> GetOrderByIdAsync(Guid id)
        {
            var order = await _orderRepository.GetByIdAsync(id);
            return _mapper.Map<OrderDto>(order);
        }

        public async Task<OrderDto> GetOrderByOrderSnAsync(string orderSn)
        {
            var order = await _orderRepository.GetByOrderSnAsync(orderSn);
            return _mapper.Map<OrderDto>(order);
        }

        public async Task<IEnumerable<OrderDto>> GetOrdersByUserIdAsync(Guid userId)
        {
            var orders = await _orderRepository.GetByUserIdAsync(userId);
            return _mapper.Map<IEnumerable<OrderDto>>(orders);
        }

        public async Task<OrderDto> MarkOrderAsCompletedAsync(Guid id)
        {
            var order = await _orderRepository.GetByIdAsync(id);
            if (order == null) return null;

            order.MarkAsCompleted();
            await _orderRepository.UpdateAsync(order);
            return _mapper.Map<OrderDto>(order);
        }

        public async Task<OrderDto> MarkOrderAsPaidAsync(Guid id)
        {
            var order = await _orderRepository.GetByIdAsync(id);
            if (order == null) return null;

            order.MarkAsPaid();
            await _orderRepository.UpdateAsync(order);
            return _mapper.Map<OrderDto>(order);
        }

        public async Task<OrderDto> MarkOrderAsShippedAsync(Guid id)
        {
            var order = await _orderRepository.GetByIdAsync(id);
            if (order == null) return null;

            order.MarkAsShipped();
            await _orderRepository.UpdateAsync(order);
            return _mapper.Map<OrderDto>(order);
        }

        public async Task<OrderDto> CancelOrderAsync(Guid id)
        {
            var order = await _orderRepository.GetByIdAsync(id);
            if (order == null) return null;

            order.Cancel();
            await _orderRepository.UpdateAsync(order);
            return _mapper.Map<OrderDto>(order);
        }

        public async Task<OrderDto> UpdateOrderAsync(Guid id, UpdateOrderDto updateOrderDto)
        {
            var order = await _orderRepository.GetByIdAsync(id);
            if (order == null) return null;

            // 使用反射或具体方法更新字段
            var orderType = order.GetType();
            orderType.GetProperty("OrderName")?.SetValue(order, updateOrderDto.OrderName);
            orderType.GetProperty("OrderTel")?.SetValue(order, updateOrderDto.OrderTel);
            orderType.GetProperty("OrderAddress")?.SetValue(order, updateOrderDto.OrderAddress);
            orderType.GetProperty("OrderRemark")?.SetValue(order, updateOrderDto.OrderRemark);
            orderType.GetProperty("UpdateTime")?.SetValue(order, DateTime.UtcNow);

            await _orderRepository.UpdateAsync(order);
            return _mapper.Map<OrderDto>(order);
        }

        private static string GenerateOrderSn()
        {
            return $"ORD{DateTime.UtcNow:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}";
        }
    }
}
